/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package ms.jasim.model.event.impl;

import ms.jasim.framework.IDescriptorProvider;
import ms.jasim.framework.IJasimAppContext;
import ms.jasim.framework.IValueProvider;
import ms.jasim.framework.JasimFramework;
import ms.jasim.model.Actor;
import ms.jasim.model.Capacity;
import ms.jasim.model.CustomizableObject;
import ms.jasim.model.Goal;
import ms.jasim.model.JasimModel;
import ms.jasim.model.JasimTemplate;
import ms.jasim.model.event.Event;
import ms.jasim.model.event.EventPackage;
import ms.jasim.model.event.ModifyObjectReaction;
import ms.jasim.model.event.PropertyModificationType;
import ms.jasim.model.items.Item;
import ms.jasim.model.items.PropertyDescriptor;
import ms.jasim.model.items.PropertyDescriptorList;
import ms.jasim.model.items.PropertyList;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Modify Object Reaction</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link ms.jasim.model.event.impl.ModifyObjectReactionImpl#getObjectVariable <em>Object Variable</em>}</li>
 *   <li>{@link ms.jasim.model.event.impl.ModifyObjectReactionImpl#getAction <em>Action</em>}</li>
 *   <li>{@link ms.jasim.model.event.impl.ModifyObjectReactionImpl#getProperty <em>Property</em>}</li>
 *   <li>{@link ms.jasim.model.event.impl.ModifyObjectReactionImpl#getNewValue <em>New Value</em>}</li>
 *   <li>{@link ms.jasim.model.event.impl.ModifyObjectReactionImpl#getDescriptorName <em>Descriptor Name</em>}</li>
 *   <li>{@link ms.jasim.model.event.impl.ModifyObjectReactionImpl#getDescriptorClass <em>Descriptor Class</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class ModifyObjectReactionImpl extends EventReactionImpl implements ModifyObjectReaction {
	/**
	 * The default value of the '{@link #getObjectVariable() <em>Object Variable</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getObjectVariable()
	 * @generated
	 * @ordered
	 */
	protected static final String OBJECT_VARIABLE_EDEFAULT = "Actor";

	/**
	 * The cached value of the '{@link #getObjectVariable() <em>Object Variable</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getObjectVariable()
	 * @generated
	 * @ordered
	 */
	protected String objectVariable = OBJECT_VARIABLE_EDEFAULT;

	/**
	 * The default value of the '{@link #getAction() <em>Action</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getAction()
	 * @generated
	 * @ordered
	 */
	protected static final PropertyModificationType ACTION_EDEFAULT = PropertyModificationType.ASSIGN;

	/**
	 * The cached value of the '{@link #getAction() <em>Action</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getAction()
	 * @generated
	 * @ordered
	 */
	protected PropertyModificationType action = ACTION_EDEFAULT;

	/**
	 * The cached value of the '{@link #getProperty() <em>Property</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getProperty()
	 * @generated
	 * @ordered
	 */
	protected PropertyDescriptor property;

	/**
	 * The cached value of the '{@link #getNewValue() <em>New Value</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getNewValue()
	 * @generated
	 * @ordered
	 */
	protected Item newValue;

	/**
	 * The default value of the '{@link #getDescriptorName() <em>Descriptor Name</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getDescriptorName()
	 * @generated
	 * @ordered
	 */
	protected static final String DESCRIPTOR_NAME_EDEFAULT = null;

	/**
	 * The cached value of the '{@link #getDescriptorName() <em>Descriptor Name</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getDescriptorName()
	 * @generated
	 * @ordered
	 */
	protected String descriptorName = DESCRIPTOR_NAME_EDEFAULT;

	/**
	 * The cached value of the '{@link #getDescriptorClass() <em>Descriptor Class</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getDescriptorClass()
	 * @generated
	 * @ordered
	 */
	protected Class<?> descriptorClass;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected ModifyObjectReactionImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return EventPackage.Literals.MODIFY_OBJECT_REACTION;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public String getObjectVariable() {
		return objectVariable;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setObjectVariable(String newObjectVariable) {
		String oldObjectVariable = objectVariable;
		objectVariable = newObjectVariable;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, EventPackage.MODIFY_OBJECT_REACTION__OBJECT_VARIABLE, oldObjectVariable, objectVariable));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public PropertyModificationType getAction() {
		return action;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setAction(PropertyModificationType newAction) {
		PropertyModificationType oldAction = action;
		action = newAction == null ? ACTION_EDEFAULT : newAction;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, EventPackage.MODIFY_OBJECT_REACTION__ACTION, oldAction, action));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public PropertyDescriptor getProperty() {
		relinkProperty();
		if (property != null && property.eIsProxy()) {
			InternalEObject oldProperty = (InternalEObject)property;
			property = (PropertyDescriptor)eResolveProxy(oldProperty);
			if (property != oldProperty) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE, EventPackage.MODIFY_OBJECT_REACTION__PROPERTY, oldProperty, property));
			}
		}
		return property;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public PropertyDescriptor basicGetProperty() {
		relinkProperty();
		return property;
	}

	private void relinkProperty() {
		if (property == null && descriptorClass != null) {
			PropertyDescriptorList list = null;
			if (!isTemplateObject()) {
				IDescriptorProvider provider = JasimFramework.getDescriptorProvider(null);
				if (provider != null)
					list = provider.getPropertyDescriptorList(descriptorClass);
			}
			else {
				JasimTemplate template = (JasimTemplate) this.getRootObject();
				if (Actor.class == descriptorClass)
					list = template.getActorDescriptors();
				else if (Goal.class == descriptorClass)
					list = template.getGoalDescriptors();
				else if (Capacity.class == descriptorClass)
					list = template.getCapacityDescriptors();
			}
			if (list != null)
				setProperty(list.get(descriptorName));
		}
	}
	
	@Override
	public boolean react(IJasimAppContext context, JasimModel model, Event event) {
		IValueProvider valueProvider = context.getService(IValueProvider.class);
		if (valueProvider != null && this.getProperty() != null) {
			Object object = valueProvider.getValue(getObjectVariable());
			if (object instanceof CustomizableObject) {
				PropertyList propertyList = ((CustomizableObject) object).getProperties();
				Item item = propertyList.get(this.getDescriptorName());
				if (item == null) {
					item = (Item) EcoreUtil.copy(((CustomizableObject) object).resolveProperty(this.getProperty()));
					propertyList.getItem().add(item);
				}
				switch(this.getAction()) {
				case ASSIGN:
					item.setValue(context, this.getNewValue().getValue(context));
					break;
				case INCREASE:
					Object newVal = this.getNewValue().getValue(context);
					Object oldVal = item.getValue(context);
					if (newVal instanceof Number && oldVal instanceof Number)
						item.setValue(context, ((Number)oldVal).intValue() + ((Number)newVal).intValue());
					break;
				}
			}
		}
		return false;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public void setProperty(PropertyDescriptor newProperty) {
		PropertyDescriptor oldProperty = property;
		property = newProperty;
		if (newProperty == null) {
			descriptorName = null;
			descriptorClass = null;
		}
		else {
			descriptorName = property.getName();
			descriptorClass = ((PropertyDescriptorList) property.eContainer()).getTargetClazz();
			if (newProperty.getItem() != null)
				if (getNewValue() == null || newProperty.getItem().getClass() != getNewValue().getClass()) {
					Item newItem = (Item) EcoreUtil.copy(property.getItem());
					setNewValue(newItem);
				}
		}
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, EventPackage.MODIFY_OBJECT_REACTION__PROPERTY, oldProperty, property));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public Item getNewValue() {
		return newValue;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public NotificationChain basicSetNewValue(Item newNewValue, NotificationChain msgs) {
		Item oldNewValue = newValue;
		newValue = newNewValue;
		if (newValue != null) {
			newValue.setName("New Value");
			newValue.setPredefined(true);
			newValue.setReservedName(true);
		}
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE, oldNewValue, newNewValue);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setNewValue(Item newNewValue) {
		if (newNewValue != newValue) {
			NotificationChain msgs = null;
			if (newValue != null)
				msgs = ((InternalEObject)newValue).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE, null, msgs);
			if (newNewValue != null)
				msgs = ((InternalEObject)newNewValue).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE, null, msgs);
			msgs = basicSetNewValue(newNewValue, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE, newNewValue, newNewValue));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public String getDescriptorName() {
		return descriptorName;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setDescriptorName(String newDescriptorName) {
		String oldDescriptorName = descriptorName;
		descriptorName = newDescriptorName;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_NAME, oldDescriptorName, descriptorName));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public Class<?> getDescriptorClass() {
		return descriptorClass;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setDescriptorClass(Class<?> newDescriptorClass) {
		Class<?> oldDescriptorClass = descriptorClass;
		descriptorClass = newDescriptorClass;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_CLASS, oldDescriptorClass, descriptorClass));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE:
				return basicSetNewValue(null, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case EventPackage.MODIFY_OBJECT_REACTION__OBJECT_VARIABLE:
				return getObjectVariable();
			case EventPackage.MODIFY_OBJECT_REACTION__ACTION:
				return getAction();
			case EventPackage.MODIFY_OBJECT_REACTION__PROPERTY:
				if (resolve) return getProperty();
				return basicGetProperty();
			case EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE:
				return getNewValue();
			case EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_NAME:
				return getDescriptorName();
			case EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_CLASS:
				return getDescriptorClass();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case EventPackage.MODIFY_OBJECT_REACTION__OBJECT_VARIABLE:
				setObjectVariable((String)newValue);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__ACTION:
				setAction((PropertyModificationType)newValue);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__PROPERTY:
				setProperty((PropertyDescriptor)newValue);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE:
				setNewValue((Item)newValue);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_NAME:
				setDescriptorName((String)newValue);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_CLASS:
				setDescriptorClass((Class<?>)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case EventPackage.MODIFY_OBJECT_REACTION__OBJECT_VARIABLE:
				setObjectVariable(OBJECT_VARIABLE_EDEFAULT);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__ACTION:
				setAction(ACTION_EDEFAULT);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__PROPERTY:
				setProperty((PropertyDescriptor)null);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE:
				setNewValue((Item)null);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_NAME:
				setDescriptorName(DESCRIPTOR_NAME_EDEFAULT);
				return;
			case EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_CLASS:
				setDescriptorClass((Class<?>)null);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case EventPackage.MODIFY_OBJECT_REACTION__OBJECT_VARIABLE:
				return OBJECT_VARIABLE_EDEFAULT == null ? objectVariable != null : !OBJECT_VARIABLE_EDEFAULT.equals(objectVariable);
			case EventPackage.MODIFY_OBJECT_REACTION__ACTION:
				return action != ACTION_EDEFAULT;
			case EventPackage.MODIFY_OBJECT_REACTION__PROPERTY:
				return property != null;
			case EventPackage.MODIFY_OBJECT_REACTION__NEW_VALUE:
				return newValue != null;
			case EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_NAME:
				return DESCRIPTOR_NAME_EDEFAULT == null ? descriptorName != null : !DESCRIPTOR_NAME_EDEFAULT.equals(descriptorName);
			case EventPackage.MODIFY_OBJECT_REACTION__DESCRIPTOR_CLASS:
				return descriptorClass != null;
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (ObjectVariable: ");
		result.append(objectVariable);
		result.append(", Action: ");
		result.append(action);
		result.append(", descriptorName: ");
		result.append(descriptorName);
		result.append(", descriptorClass: ");
		result.append(descriptorClass);
		result.append(')');
		return result.toString();
	}

} //ModifyObjectReactionImpl
